#include "mapregion.h"
#include <iostream>
#include <string>
using namespace std;

//Constants
const int OUTTER_LAYER_SIZE = 24;
const int MIDDLE_LAYER_SIZE = 16;
const int INNER_LAYER_SIZE = 8;

//Arrays holding the names of all map squares from a specific region.
string outter[OUTTER_LAYER_SIZE] = {"CITY", "FIELDS", "HILLS", "PLAINS", "WOODS", "PLAINS", "TAVERN", "FIELDS", "RUINS", "PLAINS", "FOREST", "FIELDS", "VILLAGE", "FIELDS", "GRAVEYARD", "WOODS", "SENTINEL", "HILLS", "CHAPEL", "FIELDS", "CRAGS", "PLAINS", "WOODS", "FIELDS"};
string middle[MIDDLE_LAYER_SIZE] = {"WARLOCKS CAVE", "DESSERT", "OASIS", "DESSERT", "TEMPLE", "WOODS", "RUNES", "CASTLE", "PORTAL OF POWER", "BLACK KNIGHT", "HIDDEN VALLEY", "HILLS", "CURSED GLADE", "RUNES", "CHASM", "RUNES"};
string inner[INNER_LAYER_SIZE] = {"VALLEY OF FIRE", "WEREWOLF DEN", "DICE WITH DEATH", "CRYPT", "PLAIN OF PERIL", "MINES", "VAMPIRES TOWER", "PITS"};

//Initializing a region
MapRegion::MapRegion(int area)
{
    head = new Node;
    tail = head;
    string layer;

    //using an int to differentiate between regions.
    switch (area)
    {
    case 0:
        layer = "outter";
        init(outter, OUTTER_LAYER_SIZE, layer);
        break;
    case 1:
        layer = "middle";
        init(middle, MIDDLE_LAYER_SIZE, layer);
        break;
    case 2:
        layer = "inner";
        init(inner, INNER_LAYER_SIZE, layer);
        break;
    default:
        break;
    }
}

//Building doubly linke list
void MapRegion::init(string arr[], int size, string layer)
{
    for (int i = 0; i < size; i++)
    {
        /*
            Handling the "head" of the doubly linked list seperately since
            it's a special case
         */
        if (i > 0)
        {
            MapSquare *ms = new MapSquare(arr[i], layer);
            Node *nNode = new Node;

            nNode->data = ms;
            nNode->prev = tail;
            nNode->next = head;
            tail->next = nNode;
            tail = nNode;
            head->prev = tail;
        }
        else
        {
            MapSquare *ms = new MapSquare(arr[i], layer);
            head->data = ms;
            head->next = head;
            head->prev = head;
        }
    }
}

//Returning a node based on the location given
Node* MapRegion::getMapSquare(string loc)
{
    Node *it = head;
    bool headChecked = false;

    while (it != head || !headChecked)
    {
        //handles the first element in the iteration or it will not check all nodes
        if (it == head)
        {
            headChecked = true;
        }

        if (it->data->getName() == loc)
        {
            return it;
        }
        else
        {
            it = it->next;
        }
    }
}

//Return the head of the region
Node* MapRegion::getHead()
{
    return head;
}

//Detructing the region
MapRegion::~MapRegion()
{
    // breaking the circle of map region (not sure if this is necessary)
    head->prev->next = NULL;
    head->prev = NULL;

    while (head)
    {
        Node *del = head;
        head = head->next;

        del->prev = NULL;
        del->next = NULL;
        delete del;
    }
}
